package com.suredy.app.project.model;

import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;

import com.suredy.app.project.constants.ContractLevel;
import com.suredy.core.model.BaseModel;

/**
 * 合同
 * 
 * @author VIVID.G
 * @since 2015-7-30
 * @version v0.1
 */
@Entity
@Table(name = "tb_contract", indexes = {@Index(unique = true, columnList = "no"), @Index(columnList = "name")})
public class Contract extends BaseModel {

	// 收款合同
	public final static int TYPE_COLLECTION = 0;
	// 付款合同
	public final static int TYPE_PAYMENT = 1;

	private static final long serialVersionUID = 1L;

	/* 合同编号 */
	@Column(length = 100, nullable = false)
	private String no;

	/* 合同类型（收款合同/付款合同） */
	@Column(nullable = false)
	private Integer type; // 0=收款，1=付款

	/* 合同名称 */
	@Column(length = 200, nullable = false)
	private String name;

	/* 合同金额 */
	@Column(nullable = false, columnDefinition = "float(255,2) default 0.00")
	private Float price;

	/* 结算金额 */
	@Column(columnDefinition = "float(255,2) default 0.00")
	private Float payPrice;

	/* 资金履行情况 */
	@OneToMany(mappedBy = "contract", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@Fetch(FetchMode.SUBSELECT)
	@OrderBy("date")
	private List<ContractPayment> pays;

	/* 是否为主合同 */
	@Column(nullable = false, columnDefinition = "int default 0")
	private Boolean mainContract;

	/* 合同签订日期 */
	@DateTimeFormat(iso = ISO.DATE)
	private Date signDate;

	/* 起始日期 */
	@DateTimeFormat(iso = ISO.DATE)
	private Date start;

	/* 结束日期 */
	@DateTimeFormat(iso = ISO.DATE)
	private Date end;

	/* 合同签订方 */
	@OneToMany(mappedBy = "contract", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@Fetch(FetchMode.SUBSELECT)
	@OrderBy("level")
	private List<ContractMember> members;

	/* 项目 */
	@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
	@JoinColumn(name = "project_id")
	private Project project;

	public String getNo() {
		return no;
	}

	public void setNo(String no) {
		this.no = no;
	}

	public Integer getType() {
		return type;
	}

	public void setType(Integer type) {
		this.type = type;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Float getPrice() {
		return price;
	}

	public void setPrice(Float price) {
		this.price = price;
	}

	public Float getPayPrice() {
		return payPrice;
	}

	public void setPayPrice(Float payPrice) {
		this.payPrice = payPrice;
	}

	public List<ContractPayment> getPays() {
		return pays;
	}

	public void setPays(List<ContractPayment> pays) {
		this.pays = pays;
	}

	public Boolean getMainContract() {
		return mainContract;
	}

	public void setMainContract(Boolean mainContract) {
		this.mainContract = mainContract;
	}

	public Date getSignDate() {
		return signDate;
	}

	public void setSignDate(Date signDate) {
		this.signDate = signDate;
	}

	public Date getStart() {
		return start;
	}

	public void setStart(Date start) {
		this.start = start;
	}

	public Date getEnd() {
		return end;
	}

	public void setEnd(Date end) {
		this.end = end;
	}

	public List<ContractMember> getMembers() {
		return members;
	}

	public void setMembers(List<ContractMember> members) {
		this.members = members;
	}

	public Project getProject() {
		return project;
	}

	public void setProject(Project project) {
		this.project = project;
	}

	// 以下是业务方法

	@Transient
	public ContractMember getCustomer() {
		List<ContractMember> members = this.getMembers();

		if (members == null || members.isEmpty())
			return null;

		ContractLevel level = ContractLevel.LEVEL1;

		if (Boolean.TRUE.equals(this.getMainContract()))
			level = ContractLevel.LEVEL0;

		for (ContractMember m : members) {
			if (m.getLevel().equals(level))
				return m;
		}

		return null;
	}

	@Transient
	public float getPaymentCount() {
		if (this.getPays() == null)
			return 0F;

		float count = 0F;

		for (ContractPayment p : this.getPays()) {
			if (p.getAmount() != null)
				count += p.getAmount();
		}

		return count;
	}

	@Transient
	public float getNotPaymentCount() {
		float count = this.payPrice == null ? 0 : this.payPrice.floatValue();
		float payCount = this.getPaymentCount();

		return count - payCount;
	}

	@Transient
	public float getNotPaymentRatio() {
		float notPayCount = this.getNotPaymentCount();

		float count = this.payPrice == null ? 0 : this.payPrice.floatValue();

		if (count == 0)
			return 1F;

		return (notPayCount / count);
	}

}
